import java.io.*;
import java.lang.reflect.Array;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;

public class Server {
    private static final int PORT = 20000;

    public static void main(String[] args) throws IOException {
        ServerSocket server = createServerSocket();

        initServerSocket(server);

        // 绑定到本地端口上
        server.bind(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 50);


        System.out.println("服务器准备就绪～");
        System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());


        // 等待客户端连接
        for (; ; ) {
            // 得到客户端
            Socket client = server.accept();
            // 客户端构建异步线程
            ClientHandler clientHandler = new ClientHandler(client);
            // 启动线程
            clientHandler.start();
        }
    }

    private static ServerSocket createServerSocket() throws IOException {
        // 创建基础的ServerSocket
        ServerSocket serverSocket = new ServerSocket();

        // 绑定到本地端口20000上，并且设置当前可允许等待链接的队列为50个
        //serverSocket = new ServerSocket(PORT);

        // 等效于上面的方案，队列设置为50个
        //serverSocket = new ServerSocket(PORT, 50);

        // 与上面等同
        // serverSocket = new ServerSocket(PORT, 50, Inet4Address.getLocalHost());

        return serverSocket;
    }

    private static void initServerSocket(ServerSocket serverSocket) throws IOException {
        // 是否复用未完全关闭的地址端口
        serverSocket.setReuseAddress(true);

        // 等效Socket#setReceiveBufferSize
        serverSocket.setReceiveBufferSize(64 * 1024 * 1024);

        // 设置serverSocket#accept超时时间
//         serverSocket.setSoTimeout(2000);

        // 设置性能参数:短链接，延迟，带宽的相对重要性
        serverSocket.setPerformancePreferences(1, 1, 1);
    }

    // 如果有多个客户端，需要异步连接客户端

    /**
     * 客户端消息处理
     */
    private static class ClientHandler extends Thread {
        private Socket socket;

        ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            super.run();
            // 打印客户端信息
            System.out.println("客户端信息:" + socket.getInetAddress() + "P:" + socket.getPort());

            try {
                // 得到打印流，用于数据输出；服务器回送数据
                OutputStream outputStream = socket.getOutputStream();
                InputStream inputStream= socket.getInputStream();

//                byte[] buffer =  new byte[128];
                byte[] buffer =  new byte[256];

                // 读取的字节数
                int readCount = inputStream.read(buffer);
                ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);

                // byte
                byte be = byteBuffer.get();

                // char
                char c = (char)byteBuffer.get();

                // int
                int i = byteBuffer.getInt();

                // boolean
                boolean b = byteBuffer.get() == 1;

                // Long
                long l = byteBuffer.getLong();

                // float
                float f = byteBuffer.getFloat();

                // double
                double d = byteBuffer.getDouble();

                // String
                int pos = byteBuffer.position();
                String str = new String(buffer, pos, readCount - pos - 1);

                System.out.println("收到数量" + readCount + "数据："
                        + be + "\n"
                        + c + "\n"
                        + i + "\n"
                        + b + "\n"
                        + l + "\n"
                        + f + "\n"
                        + d + "\n"
                        + str + "\n"
                );

                outputStream.write(buffer, 0, readCount); // 回送收到的长度

//                if (readCount > 0) {
//                    int value = Tools.byteArrayToInt(buffer);
//
//                    System.out.println("收到数量:" + readCount + "数据:" + value);
////                    System.out.println("收到数量:" + readCount + "数据:" + new String(buffer, 0, readCount));
////                    System.out.println("收到数量:" + readCount + "数据:" + Array.getByte(buffer, 0));
//                    // 给客户端回送一条数据
//                    outputStream.write(buffer, 0, readCount);
//
//                } else {
//                    System.out.println("没有收到:" + readCount);
//                    // 给客户端回送一条数据
//                    outputStream.write(new byte[]{0});
//
//                }

                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 连接关闭
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("客户端已退出:" + socket.getInetAddress() + "P:" + socket.getPort());

        }
    }
}
